#ifndef __iterable_hpp__
#define __iterable_hpp__

#ifdef PLATFORM_GLX

#include <GL/gl.h>

#else

#include <GLES2/gl2.h>

#endif

#include <stdint.h>
#include <math.h>

namespace testbed
{

template <
	typename TARGET_T,
	typename TRANSIENT_T >

class Iterable
{
	TRANSIENT_T m_transient;

public:

	Iterable()
	: m_transient()
	{}

	bool operator () (TARGET_T&);

	template < typename ANY_T >
	void setTransient(const ANY_T&);
};

struct CooldownTarget
{
	GLclampf r;
	GLclampf g;
	GLclampf b;
	GLclampf a;
};

struct CooldownTransient
{
	int m_value;
	int m_steps;
};

template <>
Iterable< CooldownTarget, CooldownTransient >::Iterable()
{
	m_transient.m_value = 0;
	m_transient.m_steps = 0;
}

template <>
bool Iterable< CooldownTarget, CooldownTransient >::operator () (
	CooldownTarget& color)
{
	if (m_transient.m_steps == m_transient.m_value)
		return false;

	color.r = .0625f + (m_transient.m_steps - m_transient.m_value - 1) * .0625f;
	color.g = .0625f + (m_transient.m_steps - m_transient.m_value - 1) * .0625f;
	color.b = .0625f + (m_transient.m_steps - m_transient.m_value - 1) * .0625f;
	color.a = 1.f;

	++m_transient.m_value;

	return true;
}

template <>
template <>
void Iterable< CooldownTarget, CooldownTransient >::setTransient< int >(
	const int& steps)
{
	m_transient.m_value = 0;
	m_transient.m_steps = steps;
}

struct FalloutTarget
{
	GLfloat offs;
	GLfloat luma;
};

struct FalloutTransient
{
	int m_value;
	int m_steps;
};

template <>
Iterable< FalloutTarget, FalloutTransient >::Iterable()
{
	m_transient.m_value = 0;
	m_transient.m_steps = 0;
}

template <>
bool Iterable< FalloutTarget, FalloutTransient >::operator () (
	FalloutTarget& fallout)
{
	if (m_transient.m_steps == m_transient.m_value)
		return false;

	const GLfloat span = .25f;

	fallout.offs = m_transient.m_value * span / (m_transient.m_steps - 1);
	fallout.luma = cosf(m_transient.m_value * M_PI_2 / (m_transient.m_steps - 1));

	++m_transient.m_value;

	return true;
}

template <>
template <>
void Iterable< FalloutTarget, FalloutTransient >::setTransient< int >(
	const int& steps)
{
	m_transient.m_value = 0;
	m_transient.m_steps = steps;
}

} // namespace testbed

#endif // __iterable_hpp__
